{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([[5, 1], [4, 2], [2, 5], [1, 4], [3, 2], [2, 5]])#TODO\n",
    "\n",
    "y = np.array([0, 0, 1, 1, 0, 1])#TODO  # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "knn = KNeighborsClassifier(n_neighbors=1)#TODO"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-2 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-2 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-2 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-2 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-2 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-2 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-2 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-2 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-2 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-2\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-2\" type=\"checkbox\" checked><label for=\"sk-estimator-id-2\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=1)</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsClassifier(n_neighbors=1)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X, y)# TODO"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_user = np.array([[3, 4]])\n",
    "prediction = knn.predict(new_user)#TODO"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkUAAAHJCAYAAACL5E3/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABh30lEQVR4nO3deVxU9f7H8dewg4A74oJLbrgrrmilZe43pcW8aKmpdSutzNTU682tsrIyu5WZa7cky0pvmWZo4V65UW6ZOy6o1zIQURyZ8/uDH5PIgAzMMMz4fj4e88j5nu/5ns9nzkx+POd7zjEZhmEgIiIicpPzcnUAIiIiIiWBiiIRERERVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgS4ejRo5hMJkwmU779Bg8ejMlkYvLkycUTmANkx2wymfjHP/6RZ7+MjAzKlStn7ZuQkFB8Qf6/7Fidue2EhARrjtkvHx8fwsPD6dOnD99//73Ttn2tzMxMnn/+eWrXro2fnx8mk4nBgwcXy7ZFJG8+rg5ARIrH0qVL+fe//42fn1+uZV9//TXnz593QVSuUalSJbp37w7A5cuXSUxM5Msvv+Srr77inXfe4fHHH3fq9mfNmsW0adOoUqUK9957LwEBAdx6661O3aaI3JiKIpGbQIsWLdi5cycrV64kJiYm1/KPPvoIb29vGjduzM8//1z8AQLTp09n3LhxVK9e3enbioyMZNGiRdb3hmEwdepUJk+ezLPPPst9991HWFiY07a/fPlyADZs2MAtt9zitO2IiH10+kzkJhAbG4uXlxeLFy/OtezPP/9k5cqVdO7cmfDwcBdEl6Vy5cpERkYSFBRU7Ns2mUz861//onbt2ly6dIlvv/3Wqds7ceIEgAoikRJGRZFIEaWlpTF9+nSaNWtG6dKlCQ4Opnbt2vTt25fVq1fn6p+ens706dNp0aIFwcHBBAcH065dOz744AOb45tMJmrWrMmVK1eYOnUqkZGR+Pv72zzik5fKlStz5513smLFClJSUnIs+/TTT8nIyODBBx/Md4zjx4/zj3/8gxo1auDv709YWBj33nsvW7duzdFvx44dmEwm2rZtm+dY//73vzGZTIwaNcralt+cIns/s8Lw8vKiWbNmQFau8NccpMGDB3P69GmGDRtGtWrV8PHx4c0337Sue/z4cUaMGEHt2rUJCAigXLly/O1vf2Pz5s05tpGd45EjRwByzG06evRoofMtyHeksGNmZmbyyiuvUK9ePfz9/YmIiOC5554jIyPD5noXL17klVdeoVWrVoSGhlKqVCkiIyMZPnw4v/32W67+P/74I3379qVy5cr4+flRrVo1hg0bRlJSks3xRZxJp89EiiAzM5O77rqLH3/8kQoVKtCpUycCAgI4ceIEK1eupFSpUnTr1s3a/+zZs3Tp0oVffvmF8PBwOnbsiGEYbN68mcGDB7Nt2zb+/e9/59qOxWIhJiaG9evX07FjR5o2bUr58uXtinXAgAGsWbOGzz//nCFDhljbFy9eTFBQEPfcc4/NI0kAu3bt4s477+TcuXPUr1+fe++9l6SkJJYtW8ZXX31FXFwcffv2BSAqKorIyEh++uknDh06RO3atXONl72dGxViUPjPrDAuXLgAgL+/f472//3vf7Ru3ZqrV69y6623cvnyZesRrS1bttCrVy/Onz9P/fr16dWrF//73/9YvXo133zzDYsXL6Zfv34A1nlDn332GRcvXmTQoEHWbQQHBxcp3/y+I0X5DPv378/KlSvp1KkT9evXZ8OGDbz66qucPHmSjz76KEff5ORkunTpwp49eyhbtiydOnXC39+fw4cP895771G3bl3q1atn7f/uu+/y5JNPAtC6dWtuu+029u/fz/z58/nyyy9Zt24dDRo0KODeE3EAQ+Qmd+TIEQMwbvRzGDRokAEYkyZNsrZ99913BmC0bt3auHTpUo7+KSkpxrZt23K09ezZ0wCMp59+2rh8+bK1/fTp00arVq0MwFi1alWOdbJjq1OnjnHixAm7csuO+cMPPzRSU1ONwMBA44477rAuP3bsmGEymYzY2FjDMAyjW7duBmB8//331j4Wi8Vo0qSJARhjx441LBaLddlnn31meHl5GcHBwcapU6es7dOmTTMAY+rUqbliOnjwoAEYkZGRNmO9dtuGUbjPLC/ff/+9ARgdO3bMtezMmTNGaGioARjx8fE5+gPGPffcY3MfV65c2fD29jY++uijHMu2bt1qlC1b1ggODjbOnj2bY1mNGjXy/L454ztSlDEbNGhgJCcnW9sPHz5slClTxgCMgwcP5linc+fOBmA88MADxoULF3IsO3LkiPHzzz9b32/ZssXw9vY2qlat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nDDq169vAEa5cuWM3r17G3379jWioqIMLy8vY+bMmTn6z5492/D29rb+vu69916jX79+Rtu2ba2/ofPnz+eZl4ijqSgSucaqVauMPn36GOHh4YaPj48RGhpqtGnTxnjllVeMtLS0XP0PHDhgTJw40ejQoYNRuXJlw8/Pz6hatarRuXNn4/PPP89xo8Nsly5dMt566y2jffv2RunSpQ0/Pz8jIiLC6NixozFjxgzj+PHjOfqXhKLIMLJu9PjII48YERERhq+vr1GhQgUjJibG+PHHH/Mdc/Xq1daiaODAgTeM1da27f3M8uKMosgwDCM5OdkYO3as0ahRIyMoKMgICgoyateubfTp08dYtGhRrhsZ5lcUGYZzviOOHDOvosgwDCM1NdWYOnWq0bRpUyMwMNAIDg42IiMjjREjRhgHDhzI1X/nzp3GoEGDjBo1ahh+fn5GmTJljEaNGhlDhgwxVqxYYfM3JOIsJsO45li4iIiIyE1Kc4pEREREUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFInk6cOAAXl5ebNy4sVi3m5aWho+PD//5z3+KdbsiIje7m+6SfIvFwqlTpwgJCdHzdiRft99+OxcvXmT79u0AfPHFF/zrX/8iOTmZzMxM/Pz86Nq1a46nwBdEz5492bRpU442X1/fHE8DHzRoEAkJCXk+b0xE5GZjGAYXLlygSpUqTntY8U1XFJ04cSLHYxpERETEfRw/ftzmg7kdwccpo5ZgISEhQNaHGhoa6tCxzWYz3377LV27dsXX19ehY5cEnp4f/JXjxo0bmT17Nn/++We+/du1a8epU6dISkoq8DZ69uzJ9u3bOXPmTL79qlevTsOGDR36XC9P34eenh94fo7Kz/05K8fU1FQiIiKsf487w01XFGWfMgsNDXVKURQUFERoaKhHftk9PT/4K8eNGzdSvnz5G35HLl26RHBwsF3fJR8fHy5fvkzZsmXx8vKiatWqfPzxx0RHR+foFxkZyd69ex36PfX0fejp+YHn56j83J+zc3Tm1BdNtBax4cyZM5QtWzbfPnPmzOHo0aMMHz7crrHvvPNOnnnmGT755BMmT57M77//zm233capU6dy9KtatWquJ42LiIjz3HRHikQK4urVq/j7++e5fNmyZTz++ON07tyZ8ePH2zX2888/n+P9gw8+SM2aNZkw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1asXS5YsYdu2bbz//vvFHn9WwI9hMpXCSHsTjDRyfJw+dTCVfhWTb6RrYhO5GVx/2f21EzGzjxA9/3zO9yIieXD51Wf5SUpKsj5MFaB9+/bExcUxceJEJkyYQN26dVm+fHmu4qq4mEwmKDUQgh6Ay9/C5aNZ7WUXYgpqmbVcRJyjIPchUmEkInYoUUXR9U+btvX06b59+9I3+4ZtJYTJFACBvfHyMQMrMfk1U0Ek4myZmQW7D1H28sxM58ckIm6tRBVFIiIFdoOHu+agI0QiUgAuv6O1iIiISEmgokhEREQEFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREQB87F1h1KhRNttNJhMBAQHUqVOHPn36UK5cuSIHJyIiIlJc7C6Kdu7cyY4dO8jMzKR+/foA/Pbbb3h7exMZGcm7777Ls88+y8aNG2nYsKHDAxYRERFxBrtPn/Xp04e77rqLU6dOsX37drZv386JEyfo0qULsbGxnDx5kttvv51nnnnmhmPNnj2bpk2bEhoaSmhoKNHR0axatSrP/osWLcJkMuV4BQQE2JuCiIiISC52HymaMWMG8fHxhIaGWttKly7N5MmT6dq1K08//TTPP/88Xbt2veFY1apV4+WXX6Zu3boYhsEHH3xAnz592LlzJ40aNbK5TmhoKPv377e+N5lM9qYgIiIikovdRVFKSgpnz57NdWrsf//7H6mpqQCUKVOGK1eu3HCsu+++O8f7F198kdmzZ/PDDz/kWRSZTCbCw8PtDVtEREQkX3YXRX369GHIkCG8/vrrtG7dGoCtW7cyevRoYmJiAPjpp5+oV6+eXeNmZmaydOlSLl68SHR0dJ790tLSqFGjBhaLhaioKF566aU8CyiAjIwMMjIyrO+zCzez2YzZbLYrxhvJHs/R45YUnp4feH6Oys/9eXqOys/9OSvH4vjMTIZhGPaskJaWxjPPPMN//vMfrl69CoCPjw+DBg1i5syZlCpVisTERACaN29+w/F27dpFdHQ0ly9fJjg4mLi4OHr27Gmz75YtWzhw4ABNmzYlJSWF1157jfXr17Nnzx6qVatmc53JkyczZcqUXO1xcXEEBQUVLGkRERFxqfT0dPr3709KSkqOKTyOZHdRlC0tLY3Dhw8DcMsttxAcHFyoAK5cuUJSUhIpKSl89tlnzJs3j3Xr1hXoyjWz2UyDBg2IjY1l2rRpNvvYOlIUERHBuXPnHP6hms1m4uPj6dKlC76+vg4duyTw9PzA83NUfu7P03NUfu7PWTmmpqZSoUIFpxZFdp8+yxYcHEzTpk2LHICfnx916tQBoGXLlmzdupVZs2YxZ86cG67r6+tLixYtOHjwYJ59/P398ff3t7mus76Qzhy7JPD0/MDzc1R+7s/Tc1R+7s/RORbH52V3UXTx4kVefvll1q5dy9mzZ7FYLDmWZx89KiyLxZLjyE5+MjMz2bVrV56n20REREQKyu6iaNiwYaxbt46HHnqIypUrF+mS+PHjx9OjRw+qV6/OhQsXiIuLIyEhgdWrVwMwcOBAqlatyvTp0wGYOnUq7dq1o06dOvz555/MmDGDY8eOMWzYsELHICIiIgKFKIpWrVrF119/TYcOHYq88bNnzzJw4ECSk5MpXbo0TZs2ZfXq1XTp0gWApKQkvLz+ur/k+fPneeSRRzh9+jRly5alZcuWbN68WXfOFhERkSKzuygqW7asw55rNn/+/HyXJyQk5Hg/c+ZMZs6c6ZBti4iIiFzL7sd8TJs2jeeff5709HRnxCMiIiLiEnYfKXr99dc5dOgQlSpVombNmrlmg+/YscNhwYmIiIgUF7uLouy7VouIiIh4EruLokmTJjkjDhERERGXsntOkYiIiIgnKtCRonLlyvHbb79RoUIFypYtm++9if744w+HBSciIiJSXApUFM2cOZOQkBDrn4tyw0YRERGRkqhARdGgQYOsfx48eLCzYhERERFxGbvnFHl7e3P27Nlc7b///jve3t4OCUpERESkuNldFBmGYbM9IyMDPz+/IgckIiIi4goFviT/rbfeAsBkMjFv3jyCg4OtyzIzM1m/fj2RkZGOj1BERESkGBS4KMp+5phhGLz33ns5TpX5+flRs2ZN3nvvPcdHKCIiIlIMClwUHTlyBIA77riDL774grJlyzotKBEREZHiZvcdrb///ntnxCEiIiLiUnYXRQAnTpzgyy+/JCkpiStXruRY9sYbbzgkMBEREZHiZHdRtHbtWnr37s0tt9zCr7/+SuPGjTl69CiGYRAVFeWMGEVERESczu5L8sePH8/o0aPZtWsXAQEBfP755xw/fpyOHTvSt29fZ8QoIiIi4nR2F0X79u1j4MCBAPj4+HDp0iWCg4OZOnUqr7zyisMDFBERESkOdhdFpUqVss4jqly5MocOHbIuO3funOMiExERESlGds8pateuHRs3bqRBgwb07NmTZ599ll27dvHFF1/Qrl07Z8QoIiIi4nR2F0VvvPEGaWlpAEyZMoW0tDQ++eQT6tatqyvPRERExG3ZVRRlZmZy4sQJmjZtCmSdStNdrEVERMQT2DWnyNvbm65du3L+/HlnxSMiIiLiEnZPtG7cuDGHDx92RiwiIiIiLmN3UfTCCy8wevRoVqxYQXJyMqmpqTleIiIiIu7I7onWPXv2BKB3796YTCZru2EYmEwmMjMzHRediIiISDHRA2FFREREKERR1LFjR2fEISIiIuJSds8pEhEREfFEKopEREREUFEkIiIiAri4KJo9ezZNmzYlNDSU0NBQoqOjWbVqVb7rLF26lMjISAICAmjSpAkrV64spmhFRETEkxW5KLpy5Yr1WWj2qlatGi+//DLbt29n27Zt3HnnnfTp04c9e/bY7L9582ZiY2MZOnQoO3fuJCYmhpiYGHbv3l2UFERERETsK4oWLlzIk08+yeLFiwEYP348ISEhlC5dmi5duvD777/btfG7776bnj17UrduXerVq8eLL75IcHAwP/zwg83+s2bNonv37owZM4YGDRowbdo0oqKiePvtt+3aroiIiMj1CnxJ/osvvsiLL75Ihw4diIuLY+PGjSxfvpypU6fi5eXFW2+9xcSJE5k9e3ahAsnMzGTp0qVcvHiR6Ohom322bNnCqFGjcrR169aN5cuX5zluRkYGGRkZ1vfZd902m82YzeZCxZqX7PEcPW5J4en5gefnqPzcn6fnqPzcn7NyLI7PzGQYhlGQjnXr1mXq1KnExsaybds22rZty6effsp9990HwKpVq3jsscc4duyYXQHs2rWL6OhoLl++THBwMHFxcda7Zl/Pz8+PDz74gNjYWGvbu+++y5QpUzhz5ozNdSZPnsyUKVNytcfFxREUFGRXrCIiIuIa6enp9O/fn5SUFEJDQ52yjQIf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7s9ZOaamplKhQgWnFkVuefrsWm3atGHjxo15Lvf398ff3z9Xu6+vr9O+kM4cuyTw9PzA83NUfu7P03NUfu7P0TkWx+fl9vcpSkxMpHLlyq4OQ0RERNycS48UpaWlcfDgQev7I0eOkJiYSLly5ahevTrjx4/n5MmT/Oc//wHgzTffpFatWjRq1IjLly8zb948vvvuO7799ltXpSAiIiIewqVF0bZt27jjjjus70eNGgXAoEGDWLRoEcnJySQlJVmXX7lyhWeffZaTJ08SFBRE06ZNWbNmTY4xRERERArDpUVRp06dyG+e96JFi3K8Hzt2LGPHjnVyVCIiInIzcvs5RSIiIiKOoKJIREREBBVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiJP8/vvvhIWFcfTo0WLfdrt27fj888/tWkdFkYiIiDjFiy++SJ8+fahZs6a1zWQy5XotWbLErnHXr1/P3XffTZUqVTCZTCxfvjxXn4kTJzJu3DgsFkuBx1VRJCIiIg6Xnp7O/PnzGTp0aK5lCxcuJDk52fqKiYmxa+yLFy/SrFkz3nnnnTz79OjRgwsXLrBq1aoCj+tjVxQiIiIiBbBq1Sr8/f1p165drmVlypQhPDy80GP36NGDHj165NvH29ubnj17smTJEnr16lWgcXWkSERERBxu06ZNtGzZ0uay4cOHU6FCBdq0acOCBQswDMMpMbRp04YNGzYUuL+OFImIiIjDHTt2jCpVquRqnzp1KnfeeSdBQUF8++23PPHEE6SlpfHUU085PIYqVapw/PhxLBYLXl43Pg6kokhEREQc7vLlywQEBORq/9e//mX9c4sWLbh48SIzZsxwSlEUGBiIxWIhIyODwMDAG/bX6TMRERFxuPLly3P+/Pkb9mvbti0nTpwgIyPD4TH88ccflCpVqkAFEagoEhERESdo3rw5e/fuvWG/xMREypYti7+/v8Nj2L17Ny1atChwf50+ExEREYfr0qULEydO5Pz585QtWxaAr776ijNnztCuXTsCAgKIj4/npZdeYvTo0XaNnZaWxsGDB63vjxw5QmJiIuXKlaN69erW9g0bNtC1a9cCj6sjRSIi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lJTvWLY0atQIb29v6/vKlStbjwTt378fHx8foqKirMvr1KlD2bJl7d6OiDiGj6sDEJGSaciQIYwYMQKAd955p9DjDBgwgLi4OMaNG0dcXBzdu3fPc0JyWloaLVu2ZPHixbmWVaxY0eY6f/zxB8uWLcNsNueYv5SZmcmCBQt48cUX84wtMDAQk8mUo23QoEH8/vvvzJo1ixo1auDv7090dHS+p+/y4uvrm+O9yWQq0mRuEXEuHSkSEZuy5/Fkz/O5Xu3atfHz82PTpk3WNrPZzNatW2nYsKG1rX///uzevZvt27fz2WefMWDAgDy3GRUVxYEDBwgLC6NOnTo5XqVLl7a5zuLFi6lWrRo///wziYmJ1tfrr7/OokWLyMzMtCvvTZs28dRTT9GzZ08aNWqEv78/586dy9HH19fX7nGvV79+fa5evcrOnTutbQcPHuT8+fNFGldECk9FkYjY5O3tzb59+9i7d2+OU0DZSpUqxeOPP86YMWP45ptv2Lt3L4888gjp6ekMHTrU2q9mzZq0b9+eoUOHkpmZSe/evfPc5oABA6hQoQJ9+vRhw4YNHDlyhISEBJ566ilOnDhhc5358+dz//3307hx4xyvoUOHcu7cOb755hu78q5bty4ffvgh+/bt48cff2TAgAEEBgbm6FOzZk3Wrl3L6dOnC13EREZGctddd/Hoo4/y008/sXPnTh599FGbR69EpHioKBKRPIWGhhIaGprn8pdffpn77ruPhx56iKioKA4ePMjq1atzzYsZMGAAP//8M/fcc0+uAuNaQUFBrF+/nurVq3PvvffSoEEDhg4dyuXLl23GsX37dn7++Wfuu+++XMtKly5N586dmT9/vh0ZZxVZ58+fJyoqioceesh6y4Frvf7668THxxMREZHrNgX2+M9//kOlSpW4/fbbueeee3jkkUcICQkhICCg0GOKSOGZDMMwXB2EiIjAiRMniIiIYM2aNXTu3NnV4YjcdFQUiYi4yHfffUdaWhpNmjQhOTmZsWPHcvLkSX777bdck7RFxPl09ZmIiIuYzWYmTJjA4cOHCQkJoX379ixevFgFkYiL6EiRiIiICJpoLSIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICwP8BbBeHoYvM5BMAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15) \n",
    "plt.xlabel(\"Movie A rating\")\n",
    "plt.ylabel(\"Movie B rating\")\n",
    "plt.grid()\n",
    "\n",
    "# 绘制原始样本点，要求不同的影片喜好类别用不同的颜色标记\n",
    "# 提示: 用scatter散点图绘制，用它的参数c实现不同的类别用不同的颜色标记\n",
    "#TODO\n",
    "plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', s=50)\n",
    "# 绘制新数据点，用红色x标记，大小为8\n",
    "# 提示：用plt.plot()绘制，用它的参数marker实现不同的标记符号\n",
    "#TODO\n",
    "plt.plot(new_user[0, 0], new_user[0, 1], 'rx', markersize=8)\n",
    "# 新数据最近邻索引为第一个最近邻的索引\n",
    "dist, idx = knn.kneighbors(new_user)#TODO\n",
    "nearest = X[idx[0, 0]]#TODO # 获取最近邻点的坐标，这是一个列表，第一个元素是x坐标，第二个元素是y坐标\n",
    "\n",
    "# 用红线标记新数据点与最近邻点的连接线\n",
    "# 提示：用plt.plot()绘制，用 r-- 实现红色虚线\n",
    "#TODO\n",
    "plt.plot([new_user[0, 0], nearest[0]], [new_user[0, 1], nearest[1]], 'r--')\n",
    "# 为每个点添加坐标文本  \n",
    "for x, y in zip(X[:, 0], X[:, 1]):\n",
    "    plt.text(x, y+0.1, f'({x}, {y})') \n",
    "\n",
    "# 为新数据点添加坐标文本\n",
    "plt.text(new_user[0,0], new_user[0,1]+0.1, f'({new_user[0,0]}, {new_user[0,1]})')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
